#pragma once

#include <queue>
#include <pthread.h>
// 三种关系、两种角色、一个场所
// 阻塞队列充当的是交易场所，存放的是共享资源，可以是数据也可以是任务
// 阻塞队列不能让生产者无限生产，也不能让消费者无限消费
// 需要有个容量控制生产

// 阻塞队列实现单生产和单消费
// 生产和消费之间的次数应该大致相同，需要保持同步

static const int Max_cap = 6;

template<typename T>
class Blockqueue
{
public:
    Blockqueue(int max_cap = Max_cap)
        :_max_cap(max_cap)
    {
        pthread_mutex_init(&_mutex, nullptr);
        pthread_cond_init(&_c_cond, nullptr);
        pthread_cond_init(&_p_cond, nullptr);
    }

    ~Blockqueue()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_c_cond);
        pthread_cond_destroy(&_p_cond);
        _max_cap = 0;
    }

    // 入队列
    void Equeue(const T& in)
    {
        pthread_mutex_lock(&_mutex);

        while(_block_queue.size() == _max_cap)
        {
            pthread_cond_wait(&_c_cond, &_mutex);
        }
        _block_queue.push(in);

        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_p_cond);
    }

    // 出队列
    void Pop(T* out)
    {
        pthread_mutex_lock(&_mutex);

        while(_block_queue.size() == 0)
        {
            pthread_cond_wait(&_p_cond, &_mutex);
        }

        *out = _block_queue.front();
        _block_queue.pop();

        pthread_mutex_unlock(&_mutex);
        pthread_cond_signal(&_c_cond);
    }

private:
    std::queue<T> _block_queue;

    int _max_cap;
    pthread_mutex_t _mutex;  //互斥锁

    pthread_cond_t _c_cond;  // 消费者条件变量
    pthread_cond_t _p_cond;  // 生产者条件变量
};